/**
 * Copyright (C) 2013-2014 the original author or authors.
 */
package com.foreveross.bsl.common.utils.factory;

import java.util.HashMap;


/**
 * @description
 *
 * @author rening
 * @version v1.0
 *
 * @2013-2-28
 *
 */
public class InstanceFactory {

	private static InstanceProvider instanceProvider;

	private static HashMap<Class, Object> instances=new HashMap<Class, Object>();
	
	private static HashMap<String, Object> nameInstances=new HashMap<String, Object>();
	
	public static void setInstanceProvider(InstanceProvider provider){
	     instanceProvider = provider;
	}
	
	private static InstanceProvider getInstanceProvider(){
		return instanceProvider;
	}
	
	public static <T extends Object> T getContextInstance(Class<T> clazz){
		if(instanceProvider == null){
			throw new RuntimeException("instanceProvider is null,it must be init by container or application. ");
		}
		return instanceProvider.getInstance(clazz);
	}
	
	public static <T extends Object> T getContextInstance(Class<T> clazz, String beanName){
		if(instanceProvider == null){
			throw new RuntimeException("instanceProvider is null,it must be init by container or application. ");
		}
		return instanceProvider.getInstance(clazz,beanName);
	}
	
	public static <T extends Object> T getContextInstance(String beanName){
		if(instanceProvider == null){
			throw new RuntimeException("instanceProvider is null,it must be init by container or application. ");
		}
		return (T)instanceProvider.getInstance(beanName);
	}
	
	public static <T extends Object> T getInstance(Class<T> clazz){
		T obj=null;
		obj = (T)instances.get(clazz);
		if(obj == null){
			try {
				obj = clazz.newInstance();
			} catch (InstantiationException e) {
				throw new RuntimeException("instanceFactory create instance err", e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException("instanceFactory create instance err", e);
			}
			instances.put(clazz, obj);
			nameInstances.put(clazz.getName(), obj);
		}
		return obj;
	}
	
	public static <T extends Object> T getInstance(Class<T> clazz, String beanName){
		T obj = null;
		try {
			obj = (T)nameInstances.get(beanName);
		} catch (Exception e) {
			throw new RuntimeException("the instance that be get by beanName is not instanceof clazz.",e);
		}
		if(obj == null){
			try {
				obj = clazz.newInstance();
			} catch (InstantiationException e) {
				throw new RuntimeException("instanceFactory create instance err", e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException("instanceFactory create instance err", e);
			}
			instances.put(clazz, obj);
			nameInstances.put(beanName, obj);
		}
		return (T)obj;
	}
}
